
#import "RNStorageManager.h"

#define INSTANCE [NSUserDefaults standardUserDefaults]
#define SAVE     [INSTANCE synchronize];

@implementation RNStorageManager

RCT_EXPORT_MODULE()

- (dispatch_queue_t)methodQueue
{
    return dispatch_get_main_queue();
}

+ (BOOL)requiresMainQueueSetup {
    return YES;
}

- (BOOL)contain:(NSString *)key {
    NSDictionary *dict = [INSTANCE dictionaryRepresentation];
    if ([[dict allKeys] containsObject:key]) {
        return YES;
    }
    return NO;
}

RCT_EXPORT_METHOD(commit) {
    SAVE
}

RCT_EXPORT_METHOD(clear) {
    NSDictionary *dict = [INSTANCE dictionaryRepresentation];
    for (NSString *key in [dict allKeys]) {
        [INSTANCE removeObjectForKey:key];
    }
    SAVE
}

RCT_EXPORT_METHOD(removeCache:(NSString *)key) {
    [INSTANCE removeObjectForKey:key];
    SAVE
}

/// String
RCT_EXPORT_METHOD(setString:(NSString *)key value:(NSString *)value) {
    if (key) {
        [INSTANCE setObject:value forKey:key];
    }
}

RCT_EXPORT_METHOD(setStringCommit:(NSString *)key value:(NSString *)value) {
    if (key) {
        [INSTANCE setObject:value forKey:key];
        SAVE
    }
}

RCT_EXPORT_METHOD(getString:(NSString *)key
                  defaultValue:(id)value
                  resolver:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject) {
    if (!key) {
        resolve(value);
    }
    if (![self contain:key]) {
        reject(@"-1", @"name is null.", nil);
    }
    resolve([INSTANCE stringForKey:key]);
}

/// Bool
RCT_EXPORT_METHOD(setBool:(NSString *)key value:(BOOL)value) {
    if (key) {
        [INSTANCE setBool:value forKey:key];
    }
}

RCT_EXPORT_METHOD(setBoolCommit:(NSString *)key value:(BOOL)value) {
    if (key) {
        [INSTANCE setBool:value forKey:key];
        SAVE
    }
}

RCT_EXPORT_METHOD(getBool:(NSString *)key
                  defaultValue:(id)value
                  resolver:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject) {
    if (!key) {
        resolve(value);
    } else if (![self contain:key]) {
        reject(@"-1", @"name is null.", nil);
    } else {
        BOOL ret = [INSTANCE boolForKey:key];
        resolve([NSNumber numberWithBool:ret]);
    }
}

/// Long
RCT_EXPORT_METHOD(setLong:(NSString *)key value:(NSInteger)value) {
    if (key) {
        [INSTANCE setInteger:value forKey:key];
    }
}

RCT_EXPORT_METHOD(setLongCommit:(NSString *)key value:(NSInteger)value) {
    if (key) {
        [INSTANCE setInteger:value forKey:key];
        SAVE
    }
}

RCT_EXPORT_METHOD(getLong:(NSString *)key
                  defaultValue:(id)value
                  resolver:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject) {
    if (!key) {
        resolve(value);
    }
    if (![self contain:key]) {
        reject(@"-1", @"name is null.", nil);
    }
    NSInteger ret = [INSTANCE integerForKey:key];
    resolve([NSNumber numberWithInteger:ret]);
}

/// Double
RCT_EXPORT_METHOD(setDouble:(NSString *)key value:(NSInteger)value) {
    if (key) {
        [INSTANCE setDouble:value forKey:key];
    }
}

RCT_EXPORT_METHOD(setDoubleCommit:(NSString *)key value:(NSInteger)value) {
    if (key) {
        [INSTANCE setDouble:value forKey:key];
        SAVE
    }
}

RCT_EXPORT_METHOD(getDouble:(NSString *)key
                  defaultValue:(id)value
                  resolver:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject) {
    if (!key) {
        resolve(value);
    }
    if (![self contain:key]) {
        reject(@"-1", @"name is null.", nil);
    }
    NSInteger ret = [INSTANCE doubleForKey:key];
    resolve([NSNumber numberWithInteger:ret]);
}

/// Object(Array / Dictionary)
RCT_EXPORT_METHOD(setObj:(NSString *)key value:(id)value) {
    if (key) {
        [INSTANCE setObject:value forKey:key];
    }
}

RCT_EXPORT_METHOD(setObjCommit:(NSString *)key value:(id)value) {
    if (key) {
        [INSTANCE setObject:value forKey:key];
        SAVE
    }
}

RCT_EXPORT_METHOD(getObj:(NSString *)key
                  defaultValue:(id)value
                  resolver:(RCTPromiseResolveBlock)resolve
                  rejecter:(RCTPromiseRejectBlock)reject) {
    if (!key) {
        resolve(value);
    }
    if (![self contain:key]) {
        reject(@"-1", @"name is null.", nil);
    }
    resolve([INSTANCE objectForKey:key]);
}

@end
  
